<canvas id="canvas" width="270" height="420"></canvas>
<canvas id="pattern" width="20" height="20"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.strokeRect(0, 0, canvas.width, canvas.height);

var pCanvas = document.getElementById("pattern");
var pctx = pCanvas.getContext("2d");
pctx.fillStyle = "red";
pctx.fillRect(0, 0, 20, 20);
pctx.fillStyle = "green";
pctx.fillRect(1, 1, 18, 18);
var pattern = pctx.createPattern(pCanvas, 'no-repeat');
ctx.fillStyle = pattern;
ctx.strokeStyle = "blue";

function test(testPosX, testPosY, transformCallback)
{
    ctx.save();
    ctx.beginPath();
    ctx.translate(testPosX, testPosY);
    ctx.rect(0, 0, 100, 100);
    // After transformCallback, no-repeat pattern should follow the new
    // position; but rect will stay at wherever it was.
    transformCallback();
    ctx.fill(); // See the pattern
    ctx.stroke(); // See the rect
    ctx.restore();
}

function rotateCallback() { ctx.rotate(Math.PI / 180 * 25); }
function translateCallback() { ctx.translate(50, 50); }
function scaleCallback() { ctx.scale(2, 2); }
function transformCallback() { ctx.transform(1, 1, 0, 1, 0, 0); }
function resetTransformCallback() { ctx.resetTransform() }
function multipleTransformCallback()
{
    ctx.translate(20, 20);
    ctx.rotate(Math.PI / 180 * 10);
}

// Rotate the canvas by 90 degrees
// This is to test whether after save(), restore(), the canvas can return to
// this 90-degree-rotated state instead of its very initial state
ctx.translate(canvas.width/2, canvas.height/2);
ctx.rotate(Math.PI/2);
ctx.translate(-canvas.height/2, -canvas.width/2);

// Since the canvas is rotated 90 degrees, these three rectangles will appear
// on right side, from top to bottom.
test(10, 10, scaleCallback);
test(160, 10, rotateCallback);
test(310, 10, translateCallback);

// These three rectangles will appear on left side, from top to bottom.
test(10, 160, resetTransformCallback);
test(160, 160, transformCallback);
test(310, 160, multipleTransformCallback);

</script>
